#include "gkt_board.h"
#include "gkt_debug.h"
#include "gkt_rtc.h"
#include "gkt_rand.h"
#include "gkt_flash_partition.h"
#include "gkt_user.h"
#include "gkt_os.h"

typedef struct _user_test_password_item {
	uint32_t	user_index;
	uint8_t	authority;
	uint8_t	length;
	uint8_t	data[GKT_USER_PASSWORD_MAXSIZE];
} user_test_password_item_s;

typedef struct _user_test_card_item {
	uint32_t	user_index;
	uint8_t	authority;
	uint8_t	length;
	uint8_t	data[GKT_USER_CARD_ID_MAXSIZE];
} user_test_card_item_s;

typedef struct _user_test {
	uint32_t	item_nums[GKT_USER_TYPE_MAX];
	uint32_t	item_auth_nums[GKT_USER_TYPE_MAX][GKT_USER_AUTH_TEMPORARY];

	user_test_password_item_s	password_items[GKT_USER_PASSWORD_MAXNUMS];
	user_test_card_item_s	card_items[GKT_USER_CARD_MAXNUMS];
} user_test_s;
static user_test_s s_user_test;

enum {
	USER_TEST_ENROLL_0 = 0,
	USER_TEST_VERIFY_0,
	USER_TEST_DELETE,
	USER_TEST_ENROLL_1,
	USER_TEST_VERIFY_1,
	USER_TEST_DELETE_GROUP,
	USER_TEST_ENROLL_2,
	USER_TEST_VERIFY_2,
	USER_TEST_RESET,
	USER_TEST_ENROLL_3,
	USER_TEST_VERIFY_3,
	USER_TEST_MAX
};

static void user_test(void)
{
	gkt_user_amount_s amount;
	uint32_t action, user_index, authority, type, total_nums, length, i;
	uint8_t data[32];
	uint32_t sleep_time;
	int retval;

	while (1) {
		action = gkt_rand() % USER_TEST_MAX;
		if ((USER_TEST_ENROLL_0 == action)
			|| (USER_TEST_ENROLL_1 == action)
			|| (USER_TEST_ENROLL_2 == action)
			|| (USER_TEST_ENROLL_3 == action))
		{
			authority = gkt_rand() % GKT_USER_AUTH_TEMPORARY;
			type = (gkt_rand() & 0x01) ? GKT_USER_TYPE_PASSWORD : GKT_USER_TYPE_CARD;
			gkt_info("USER_TEST: ENROLL - authority(%u), type(%u)\n",
						authority, type);
	
			if (GKT_USER_TYPE_PASSWORD == type) {
				gkt_user_get_amount(amount, authority, type);
				if (amount.used_nums != s_user_test.password_item_auth_nums[authority]) {
					gkt_error("USER_TEST: ENROLL - nums unmatch - %u / %u\n", amount.used_nums, 
							s_user_test.password_item_auth_nums[authority]);
					GKT_ASSERT(0);
					goto loop_next;
				}
				else if if (amount.used_nums == amount.max_nums) {
					gkt_info("USER_TEST: ENROLL - FULL!\n");
					goto loop_next;
				}

				gkt_user_get_amount(amount, authority, type);
				if (s_user_test.password_item_nums == GKT_USER_PASSWORD_MAXNUMS) {
					gkt_error("USER_TEST: ENROLL - FULL UNMATCH!\n");
					GKT_ASSERT(0);
					goto loop_next;
				}
				
				length = GKT_USER_PASSWORD_MINSIZE + 
					(gkt_rand() % (GKT_USER_PASSWORD_MAXSIZE - GKT_USER_PASSWORD_MINSIZE + 1));
				for (i = 0; i < length; i++)
					data[i] = (gkt_rand() % 10) + '0';
			}
			else {	/* GKT_USER_TYPE_CARD == type */
				if (amount.used_nums != s_user_test.card_item_auth_nums[authority]) {
					gkt_error("USER_TEST: ENROLL - nums unmatch - %u / %u\n",
								amount.used_nums, s_user_test.card_item_auth_nums[authority]);
					GKT_ASSERT(0);
					goto loop_next;
				}
				else if (s_user_test.card_item_nums == GKT_USER_CARD_MAXNUMS) {
					gkt_error("USER_TEST: ENROLL - FULL UNMATCH!\n");
					GKT_ASSERT(0);
					goto loop_next;
				}

				length = 4;
				for (i = 0; i < 4; i++)
					data[i] = (uint8_t)(gkt_rand() & 0xff);
			}

			user_index = gkt_user_get_free_index();
			if ((user_index < GKT_USER_INDEX_MIN)
				|| (user_index > GKT_USER_INDEX_MAX))
			{
				gkt_error("USER_TEST: ENROLL - get free user_index(%u) failed!\n", user_index);
				GKT_ASSERT(0);
				goto loop_next;
			}

			retval = gkt_user_enroll_init(type, authority, user_index);
			if (retval != GKT_SUCCESS) {
				gkt_info("USER_TEST: ENROLL - init failed %d\n", retval);
				GKT_ASSERT(0);
				goto loop_next;
			}

			retval = gkt_user_enroll(type, data, length);
		}
		else if ((USER_TEST_VERIFY_0 == action)
			|| (USER_TEST_VERIFY_1 == action)
			|| (USER_TEST_VERIFY_2 == action)
			|| (USER_TEST_VERIFY_3 == action))
		{

		}

loop_next:
		sleep_time = (gkt_rand() % 1000) + 1;
		gkt_thread_sleep(sleep_time);
	}
}

void gkt_app_main(void *params)
{
	int retval;

	gkt_trace("app_main: start ...\n");

	check_or_set_default_date_time();

	retval = gkt_flash_partition_init();
	if (retval != GKT_SUCCESS) {
		gkt_error("app_main: flash partition init failed %d\n", retval);
		return;
	}

	/* user manager init */
	gkt_user_init();

	user_test();

	GKT_ASSERT(0);
}

